package socket;
//ipconfig查看ip地址
import Lambda.T;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
 *聊天室的服务端
 * */
public class Server {
//    private List<PrintWriter> allOut=new ArrayList<>();
    private Map<String,PrintWriter> allOut=new HashMap<>();
    private ExecutorService threadPool;
    private ServerSocket serverSocket;//类似于交换机
    private Server(){
        try {
            System.out.println("正在启动服务端...");
            serverSocket=new ServerSocket(8088);
            threadPool = Executors.newFixedThreadPool(40);
            System.out.println("服务端启动完毕!");

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void start(){
        try {
            while(true){
            System.out.println("等待客户端连接...");
            Socket socket=serverSocket.accept();
            System.out.println("一个客户端连接了!");
            ClientHandler handler=new ClientHandler(socket);
//            Thread t=new Thread(handler);
//            t.start();
            threadPool.execute(handler);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        Server server=new Server();
        server.start();
    }
    private  class ClientHandler implements Runnable{
        private Socket socket;
        private String host;
        private String nickName;
        public ClientHandler(Socket socket){
            this.socket=socket;
            this.host=socket.getInetAddress().getHostAddress();
        }
        public void run(){
            PrintWriter pw=null;
            try {
                InputStream is=socket.getInputStream();
                InputStreamReader isr=new InputStreamReader(is, StandardCharsets.UTF_8);
                BufferedReader br=new BufferedReader(isr);
                nickName=br.readLine();


                OutputStream out=socket.getOutputStream();
                OutputStreamWriter osw=new OutputStreamWriter(out, StandardCharsets.UTF_8);
                BufferedWriter bw=new BufferedWriter(osw);
                 pw=new PrintWriter(bw,true);
                 synchronized (allOut){
                     //将该输出流存入到共享集合allOut中
//                     allOut.add(pw);
                     int num=1;
                     String newNickname=nickName;
                     while(true) {
                         if(allOut.containsKey(newNickname)){
                             newNickname=nickName+num;
                             num++;
                         }else{
                                allOut.put(newNickname, pw);
                                nickName=newNickname;
                                break;
                         }
                     }
                 }

                //告知所有客户端该用户上线了
                SendMessage(nickName+"上线了,当前在线人数:"+allOut.size());
                String message;
                while((message=br.readLine())!=null) {
                    if(message.startsWith("@")){
                        SendMessageToSomeOne(message);
                    }else{
                    SendMessage(("["+nickName+"]"+"("+host+")说: " + message));
                    saveMessage(nickName,null,message);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();//异常输出
            }finally {
                synchronized (allOut){
//                allOut.remove(pw);
                    allOut.remove(nickName);
                }
                //通知所有客户端,该用户下线了
                SendMessage(nickName+"下线了,当前在线人数:"+allOut.size());
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        /*
        * 将给定消息发送给客户端
        * @param message*/
        public void SendMessage(String message){
            System.out.println(message);
            synchronized (allOut) {

                for (PrintWriter o : allOut.values()) {
                    o.println(message);
                }
            }
        }
        /*
        * 私聊功能
        * @para message 私聊格式应当是：@昵称：消息
        * */
        public void SendMessageToSomeOne(String message){
            if(message.matches("@.+:.+")) {
                //1
                String toNickName = message.substring(1, message.indexOf(":"));
                //2
                if (allOut.containsKey(toNickName)) {
                    PrintWriter pw = allOut.get(toNickName);
                    message=message.substring(message.indexOf(":")+1);
                    String toMessage = nickName + "悄悄对你说:" + message;
                    pw.println(toMessage);
                    saveMessage(toNickName,nickName,message);
                } else {//对方不存在
                    //用当前用户的昵称获取自己的输出流，通知他没有该用户
                    PrintWriter pw = allOut.get(nickName);
                    pw.println(toNickName + "不在线");
                }
            }else{
                PrintWriter pw = allOut.get(nickName);
                pw.println("私聊格式不正确，正确格式:@对方昵称:消息内容");
            }
        }
        private void saveMessage(String fromUser,String toUser,String message){
            try (Connection connection = DBUtil.getConnection()){
                String sql="insert into chatinfo(content,from_user,to_user)" +
                        " values(?,?,?)";
                PreparedStatement ps = connection.prepareStatement(sql);
                ps.setString(1,message);
                ps.setString(2,fromUser);
                ps.setString(3,toUser);
                ps.executeUpdate();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
